package dcli;


import dcli.ClientConnection;
import dcli.ControlDcli;
import dcli.ErrorHandler;
import dcli.Promtp;
import java.io.File;
import java.util.Iterator;
import java.util.List;

/**
 * Universidad Simón Bolívar
 * Curso de Redes I - Taller
 * Profesor: Ricardo Gonzalez
 * Trimestre Enero-Marzo 2011
 *
 * Proyecto 2 RD
 * Se desea implementar un sistema de repositorios de archivos, que llamaremos
 * Repositorios Distribuidos o RD, estos repositorios estarán constituidos por
 * tres tipos de componentes diferentes: uno de ellos será un programa que
 * llamaremos drep que se encargará de recibir, almacenar y entregar archivos
 * que sea subidos o solicitados por otros programas, los componentes dcli
 * serán programas que enviarán o solicitarán archivos a los programas drep del
 * sistema, en función de los requerimientos de los usuarios con los que
 * interactúan en su pantalla. Pueden existir varias instancias de programas
 * drep y de programas dcli en el sistema, pero debe existir una única instancia
 * del programa dmon, este último componente se encargará de llevar una serie de
 * datos de las operaciones que los programas dcli realizan en todos los
 * programas drep del sistema.
 *
 * Programa dcli
 * Los programas dcli serán los clientes principales del sistema y deberán,
 * tanto esperar comandos de los usuarios por la consola, como realizar
 * consultas u otras operaciones sobre los programas drep correspondientes,
 * en función de los comandos que el programa dcli reciba.
 *
 * La sintaxis de la llamada a este programa será la siguiente:
 * dcli [-h <host de un drep>] [-p <puerto de un drep>] [-d <ldirectorio>]
 *      [-a <archivo>] [-n <nombre>]
 *
 * @author Grupo 9
 * @author Richard Simoes Ferreira
 * @author Ricardo Tocco
 *
 * @version 1.0
 */


public class Main {

    /**
     * Función para capturar y verificar los parámetro introdcidos por el
     * usuario.
     *
     * @param args  lista de los parámetros de entrada
     * @return      Un apuntador a la estructura de control ControlDcli
     *              que agrupa toda la información necesaria para la correcta
     *              ejecución de los programas dcli.
     */
    private static ControlDcli capturarParametros(String[] args){

        ErrorHandler errorH = new ErrorHandler();

        boolean flag_host = false;
        boolean flag_puerto = false;
        boolean flag_ldir = false;
        boolean flag_arch = false;
        boolean flag_nombre = false;

        //Defaults
        String host = "127.0.0.1";
        int puerto = 18000;
        String ldir = System.getProperty("user.dir"); // directorio local
        String arch = null;
        String nombre = "default";

        ControlDcli control;

        //Verificamos si solicita ayuda
        if (args.length == 1){
            if (args[0].equals("--help")){
                ErrorHandler.imprimirAyudaUsage();
            } else {
                errorH.argumentosInvalidos();
            }
        }

        
        if (args.length > 10) {
            //Mayor cantidad que el max de argumentos permitidos
            errorH.argumentosInvalidos();

        } else {

            for ( int i = 0 ; i < args.length ; i++ ) {

                if (args[i].equals("-h")) {

                    if (!flag_host) {
                        host = args[++i];
                        flag_host = true;
                    } else {
                        errorH.redifinicionArgumento("host (-h)");
                    }

                }  else if (args[i].equals("-p")) {

                    if (!flag_puerto) {
                        if (puerto <= 1024 && puerto >= 65535)
                            errorH.puertoInvalido(puerto);
                        else {
                            puerto = Integer.valueOf(args[++i]);
                            flag_puerto = true;
                        }
                    } else {
                        errorH.redifinicionArgumento("puerto (-p)");
                    }

                } else if (args[i].equals("-d")) {

                    if (!flag_ldir) {
                        ldir =  args[++i];
                        flag_ldir = true;
                        //Verificar directorio
                        File verificarLdir = new File(ldir);
                        if (!verificarLdir.isDirectory()){
                            errorH.directorioNoExiste();
                        } else {
                            if (!ldir.endsWith("/")) ldir += "/";
                        }
                    } else {
                        errorH.redifinicionArgumento("ldirectorio (-d)");
                    }

                }else if (args[i].equals("-a")) {

                    if (!flag_arch) {
                        arch =  args[++i];
                        flag_arch = true;
                        //Verificar archivo
                        File verificarArch = new File(arch);
                        if (!verificarArch.exists()){
                            errorH.archivoNoExiste();
                        }
                    } else {
                        errorH.redifinicionArgumento("archivo (-a)");
                    }

                }else if (args[i].equals("-n")) {

                    if (!flag_nombre) {
                        nombre =  args[++i];
                        flag_nombre = true;

                    } else {
                        errorH.redifinicionArgumento("nombre (-n");
                    }

                } else {
                    errorH.parametroInvalido();
                }
            }
        }

        control = new ControlDcli(puerto,host,ldir,arch,nombre,null);
        return control;
    }


    /**
     * Función Principal para el programa dcli.
     *
     * @param args  lista de los parámetros de entrada
     * @return      0 si la ejecución es exitosa o cualquier otro valor en
     *              caso de error.
     */
    public static void main(String[] args) /*throws FileNotFoundException*/ {
        
        ControlDcli control;
        ClientConnection cliente;
        Promtp promtp;
        
        control = capturarParametros(args);

        cliente = new ClientConnection(control.getPuertoDrep(),
                control.getServidorDrep(),control);
        control.setClienteDrep(cliente);
        promtp = new Promtp(control);

        cliente.Connect();

        if (control.getArchivo()!=null){
            boolean fin = false;
            fin = ejecutar_archivo(control);
            if (fin){
                cliente.Disconnect();
                System.exit(0);
            }
        }

        promtp.run();

        //Terminar
        cliente.Disconnect();
        System.exit(0);

    }

    /**
     * Implementa la ejecución automatizada de comandos aceptados por dcli, esto
     * a través de la lectura del archivo arch que en cada línea contiene uno
     * de los comandos que puede usar un programa dcli.
     */
    public static boolean ejecutar_archivo (ControlDcli control){
        List<String> comandos = control.getComandosArch();
        Iterator<String> iter = comandos.listIterator();
        boolean flag = false;
        Promtp promtp = new Promtp (control);

        while(iter.hasNext()){
            String entrada = (String)iter.next();
            System.out.println("comando: "+entrada);
            flag = promtp.ejecutar_archivo(entrada);
            if (flag) {
                break;
            }
        }
        return flag;

    }

}
